package com.vmj.instructions.references;

import com.vmj.common.BytesReader;
import com.vmj.heap.ArrayTypes;
import com.vmj.heap.VMClass;
import com.vmj.heap.ClassLoader;
import com.vmj.heap.VMObject;
import com.vmj.instructions.base.Instruction;
import com.vmj.rtda.Frame;
import com.vmj.rtda.OperandStack;

/**
 * Created by yangshoujun on 2017/9/9 上午1:15.
 */
public class NewArray implements Instruction {

    byte aType;

    public void fetchOperands(BytesReader reader) {
        aType = reader.readByte();
    }

    public void execute(Frame frame) {
        OperandStack stack = frame.getOperandStack();
        int count = stack.popInt();
        if(count < 0) {
            throw new RuntimeException("java.lang.NagativeArraySizeException");
        }

        ClassLoader classLoader = frame.getMethod().getClazz().getClassLoader();
        VMClass clazz = getPrimitiveArrayClass(classLoader, aType);
        VMObject arr = VMObject.newArray(clazz, count);
        stack.pushRef(arr);
    }

    private VMClass getPrimitiveArrayClass(ClassLoader classLoader, byte aType) {
        switch (aType) {
            case ArrayTypes.AT_BOOLEAN:
                return classLoader.loadClass("[Z");
            case ArrayTypes.AT_BYTE:
                return classLoader.loadClass("[B");
            case ArrayTypes.AT_CHAR:
                return classLoader.loadClass("[C");
            case ArrayTypes.AT_SHORT:
                return classLoader.loadClass("[S");
            case ArrayTypes.AT_INT:
                return classLoader.loadClass("[I");
            case ArrayTypes.AT_FLOAT:
                return classLoader.loadClass("[F");
            case ArrayTypes.AT_LONG:
                return classLoader.loadClass("[L");
            case ArrayTypes.AT_DOUBLE:
                return classLoader.loadClass("[D");
            default:
                throw new RuntimeException("invalid array type: " + aType);
        }
    }
}
